import sys

from PyQt5.QtWidgets import QLineEdit, QCompleter
from PyQt5.QtCore import Qt, QObject, pyqtSignal
import json
import os
from typing import Dict, List

#  self.force_input = HistoryLineEdit("pulling_force", self)

class HistoryManager(QObject):
    """
    历史记录管理器 - 单例模式
    负责管理所有输入框的历史记录
    """
    _instance = None
    history_updated = pyqtSignal(str, list)  # 信号：字段名, 历史记录列表

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(HistoryManager, cls).__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if self._initialized:
            return

        super().__init__()
        self.history_file = "input_history.json"
        self.history_data: Dict[str, List[str]] = {}
        self.load_history()
        self._initialized = True

    def load_history(self):
        """从文件加载历史记录"""
        try:
            if os.path.exists(self.history_file):
                with open(self.history_file, 'r', encoding='utf-8') as f:
                    self.history_data = json.load(f)
        except Exception as e:
            print(f"加载历史记录失败: {e}")
            self.history_data = {}

    def save_history(self):
        """保存历史记录到文件"""
        try:
            with open(self.history_file, 'w', encoding='utf-8') as f:
                json.dump(self.history_data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存历史记录失败: {e}")

    def add_history(self, field_name: str, value: str):
        """为指定字段添加历史记录"""
        if not value or not value.strip():
            return

        value = value.strip()

        # 初始化字段历史记录
        if field_name not in self.history_data:
            self.history_data[field_name] = []

        # 如果值已存在，先移除
        if value in self.history_data[field_name]:
            self.history_data[field_name].remove(value)

        # 添加到开头
        self.history_data[field_name].insert(0, value)

        # 限制历史记录数量（最多20条）
        if len(self.history_data[field_name]) > 20:
            self.history_data[field_name] = self.history_data[field_name][:20]

        # 保存并发出更新信号
        self.save_history()
        self.history_updated.emit(field_name, self.history_data[field_name])

    def get_history(self, field_name: str) -> List[str]:
        """获取指定字段的历史记录"""
        return self.history_data.get(field_name, [])

    def clear_history(self, field_name: str = None):
        """清除历史记录"""
        if field_name:
            if field_name in self.history_data:
                del self.history_data[field_name]
        else:
            self.history_data.clear()

        self.save_history()
        if field_name:
            self.history_updated.emit(field_name, [])
        else:
            # 发出所有字段的更新信号
            for field in list(self.history_data.keys()):
                self.history_updated.emit(field, [])


class HistoryLineEdit(QLineEdit):
    """
    历史记录输入框
    支持自动完成和历史记录管理
    """
    # 信号：当用户输入新值时发出
    value_changed = pyqtSignal(str)

    def __init__(self, field_name=None, parent=None):
        super().__init__(parent)
        # 如果提供了field_name，则使用它，否则使用默认值
        self.field_name = field_name if field_name is not None else 'AAADefault'
        self.history_manager = HistoryManager()
        self.completer = None

        self.setup_ui()
        self.load_history()
        self.connect_signals()

    def set_field_name(self, field_name: str):
        """设置字段名"""
        self.field_name = field_name

    def setup_ui(self):
        """设置UI"""
        # 创建自动完成器
        self.completer = QCompleter(self.history_manager.get_history(self.field_name))
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setFilterMode(Qt.MatchContains)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setMaxVisibleItems(10)  # 设置最大显示项数

        # 设置自动完成器
        self.setCompleter(self.completer)
        
        # 设置完成器弹出窗口的最小宽度
        if self.completer.popup():
            self.completer.popup().setMinimumWidth(200)  # 设置最小宽度为200像素

    def load_history(self):
        """加载历史记录"""
        history = self.history_manager.get_history(self.field_name)

        # 更新自动完成器
        if self.completer:
            from PyQt5.QtCore import QStringListModel
            model = QStringListModel(history)
            self.completer.setModel(model)

    def connect_signals(self):
        """连接信号"""
        # 当输入框失去焦点或用户按下回车时，保存历史记录
        self.editingFinished.connect(self.on_editing_finished)
        self.history_manager.history_updated.connect(self.on_history_updated)

        # 当文本变化时，显示所有历史记录
        self.textEdited.connect(self.on_text_edited)

    def mousePressEvent(self, event):
        """鼠标点击事件处理，点击时显示所有历史记录"""
        # 先调用父类方法，确保光标正确定位
        super().mousePressEvent(event)
        
        # 延迟一点显示历史记录，确保输入框获得焦点
        from PyQt5.QtCore import QTimer
        QTimer.singleShot(10, lambda: self._trigger_history_display())
    
    def _trigger_history_display(self):
        """触发历史记录显示的辅助方法"""
        # 确保输入框获得焦点
        self.setFocus(Qt.MouseFocusReason)
        
        # 显示所有历史记录
        self.show_all_history()
        
        # 如果有完成器，重新计算并显示完成列表
        if self.completer and self.completer.popup():
            rect = self.cursorRect()
            self.completer.complete(rect)

    def on_text_edited(self, text):
        """文本编辑时的处理"""
        # 当用户开始输入时，显示匹配的历史记录
        if self.completer:
            self.completer.setCompletionPrefix(text)
            # 设置完成器弹出窗口的最小宽度
            popup = self.completer.popup()
            if popup:
                popup.setMinimumWidth(max(200, self.width()))  # 至少200像素，或者与输入框同宽
                
            if text:  # 如果有文本，显示匹配项
                self.completer.complete()
            else:  # 如果没有文本，显示所有历史记录
                self.show_all_history()

    def show_all_history(self):
        """
        显示所有历史记录
        """
        if not self.completer:
            return
            
        # 获取所有历史记录
        history = self.history_manager.get_history(self.field_name)
        
        # 确保模型已更新
        from PyQt5.QtCore import QStringListModel
        if history:
            # 更新完成器的模型
            model = QStringListModel(history)
            self.completer.setModel(model)
            
            # 清除前缀，显示所有历史记录
            self.completer.setCompletionPrefix("")
            
            # 设置完成器弹出窗口的最小宽度
            popup = self.completer.popup()
            if popup:
                popup.setMinimumWidth(max(200, self.width()))
                # 确保弹出窗口能正确显示
                popup.setFocusPolicy(Qt.StrongFocus)
                popup.setFocusProxy(self)
            
            # 获取光标位置的矩形区域，稍微向下调整以确保弹出窗口可见
            rect = self.cursorRect()
            rect.setWidth(self.width())  # 使用整个输入框的宽度
            rect.translate(0, rect.height())  # 移动到输入框下方
            
            # 强制显示完成列表
            self.completer.complete(rect)
            
            # 强制刷新弹出窗口
            if popup:
                popup.show()
                popup.raise_()
        else:
            # 如果没有历史记录，隐藏完成列表
            popup = self.completer.popup()
            if popup:
                popup.hide()

    def on_editing_finished(self):
        """编辑完成时的处理"""
        current_text = self.text().strip()
        if current_text:
            self.history_manager.add_history(self.field_name, current_text)
            self.value_changed.emit(current_text)

    def on_history_updated(self, field_name: str, history: list):
        """当历史记录更新时的处理"""
        if field_name == self.field_name:
            self.load_history()

    def set_value(self, value: str):
        """设置当前值"""
        self.setText(value)

    def get_value(self) -> str:
        """获取当前值"""
        return self.text().strip()
